#include "Engine.hpp"
#include <iostream>
#include "PlayerController.hpp"

Engine::Engine() : engineMode(EngineMode::EditorEngineMode), editor(nullptr), window(nullptr), renderer(nullptr)
    , isRunning(false), lastUpdateTime(0){

}

Engine::~Engine() {
    shutdown();
}

bool Engine::initialize(const char* title, int width, int height) {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cerr << "SDL could not initialize: " << SDL_GetError() << std::endl;
        return false;
    }
    
    if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1")) {
        std::cerr << "Warning: Linear texture filtering not enabled!" << std::endl;
    }
    
    window = SDL_CreateWindow(title, 
                             SDL_WINDOWPOS_UNDEFINED, 
                             SDL_WINDOWPOS_UNDEFINED, 
                             width, 
                             height, 
                             SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
    
    if (!window) {
        std::cerr << "Window could not be created: " << SDL_GetError() << std::endl;
        return false;
    }
    
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (!renderer) {
        std::cerr << "Renderer could not be created: " << SDL_GetError() << std::endl;
        return false;
    }
    
    SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
    
    int imgFlags = IMG_INIT_PNG;
    if (!(IMG_Init(imgFlags) & imgFlags)) {
        std::cerr << "SDL_image could not initialize: " << IMG_GetError() << std::endl;
        return false;
    }
    
    if (TTF_Init() == -1) {
        std::cerr << "SDL_ttf could not initialize: " << TTF_GetError() << std::endl;
        return false;
    }
    
    // 初始化场景管理器
    m_sceneManager = std::make_unique<SceneManager>(this);

    // 初始化脚本管理器以及注册脚本
    m_scriptManager = std::make_unique<ScriptManager>();
    m_scriptManager->RegisterScript<PlayerController>("PlayerController");

    editor = new Editor(this);
    game = new Game(this);

    // 初始化编辑器
    if (!editor->initialize()) {
        std::cerr << "Failed to initialize editor!" << std::endl;
        return false;
    }

    if (!game->initialize()) {
        std::cerr << "Failed to initialize game!" << std::endl;
        return false;
    }
    
    isRunning = true;
    lastUpdateTime = SDL_GetTicks();
    
    return true;
}

void Engine::run() {
    while (isRunning) {
        Uint32 frameStart = SDL_GetTicks();
        
        processInput();
        
        Uint32 currentTime = SDL_GetTicks();
        float deltaTime = (currentTime - lastUpdateTime) / 1000.0f;
        lastUpdateTime = currentTime;

        update(deltaTime);
        render();
        
        Uint32 frameTime = SDL_GetTicks() - frameStart;
        if (frameTime < FRAME_DELAY) {
            SDL_Delay(FRAME_DELAY - frameTime);
        }
    }
}

void Engine::shutdown() {

    if (editor) {
        editor->shutdown();
        delete editor;
        editor = nullptr;        
    }
    
    if (game) {
        game->shutdown();
        delete game;
        game = nullptr;        
    }

    ResourceManager::getInstance().cleanup();
    
    if (renderer) {
        SDL_DestroyRenderer(renderer);
        renderer = nullptr;
    }
    
    if (window) {
        SDL_DestroyWindow(window);
        window = nullptr;
    }
    
    TTF_Quit();
    IMG_Quit();
    SDL_Quit();
}

void Engine::processInput() {

    if (engineMode == EngineMode::EditorEngineMode) {
        editor->processInput();
    }
    else if (engineMode == EngineMode::GameEngineMode) {
        game->processInput();
    }
}

void Engine::update(float deltaTime) {
    if (engineMode == EngineMode::EditorEngineMode) {
        editor->update(deltaTime);        
    }
    else if (engineMode == EngineMode::GameEngineMode) {
        game->update(deltaTime);  
    }
}

void Engine::render() {
    if (engineMode == EngineMode::EditorEngineMode) {
        editor->render();
    }
    else if (engineMode == EngineMode::GameEngineMode) {
        game->render();
    }
}

entt::registry& Engine::getRegistry() {
    if (m_sceneManager->getCurrentScene())
    {
        return m_sceneManager->getCurrentScene()->getRegistry();
    }
    return registry;
}

entt::entity Engine::createEntity() {
    return getRegistry().create();
}

void Engine::destroyEntity(entt::entity entity) {
    getRegistry().destroy(entity);
}